package com.atguigu.tingshu.search.runable;

import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.search.factory.ScheduleTaskThreadFactory;
import com.atguigu.tingshu.search.service.impl.ItemServiceImpl;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.util.CollectionUtils;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 任务（重建布隆）
 */
public class RebuildDistroBloomFilterRunnable implements Runnable {

    private RedissonClient redissonClient;


    private ItemServiceImpl itemServiceImpl;
    private StringRedisTemplate redisTemplate;

    Logger logger = LoggerFactory.getLogger(this.getClass());


    public RebuildDistroBloomFilterRunnable(RedissonClient redissonClient,StringRedisTemplate redisTemplate, ItemServiceImpl itemServiceImpl) {
        this.redissonClient = redissonClient;
        this.redisTemplate = redisTemplate;
        this.itemServiceImpl = itemServiceImpl;

    }

    @Override
    public void run() {
        // 重建布隆
        // 删除老布隆  在新建一个新布隆  最后用新布隆替换老布隆
        // 1.删除老布隆的数据
        // 2.删除老布隆的配置
        // 3.创建一个新布隆
        // 4.查询最新的数据同步给新布隆
        // 5.用新布隆替换老布隆


        // 优化：删除老布隆和新建布隆以及放数据和替换做为一个原子操作
        // 1.先创建一个新布隆&&初始化  2.将数据放到新布隆中  3.删除老布隆数据 4.删除老布隆配置 5.用新布隆替换老布隆  and 1-5原子操作  （3-5做原子操作）
        RBloomFilter<Object> newBloomFilter = redissonClient.getBloomFilter("albumIdBloomFilter:new");
        newBloomFilter.tryInit(800000, 0.03);
        List<Long> albumIds = itemServiceImpl.getAlbumIds();
        if (!CollectionUtils.isEmpty(albumIds)) {
            for (Long albumId : albumIds) {
                newBloomFilter.add(albumId);
            }
            logger.info("新的分布式布隆过滤器数据初始化完毕，且元素个数为：{}", newBloomFilter.count());
        }

        String script = " redis.call(\"del\",KEYS[1])" + "  redis.call(\"del\",KEYS[2])" + "  redis.call(\"rename\",KEYS[3],KEYS[1])" + "  redis.call(\"rename\",KEYS[4],KEYS[2]) return 1";
        List<String> asList = Arrays.asList("albumIdBloomFilter", "{albumIdBloomFilter}:config", "albumIdBloomFilter:new", "{albumIdBloomFilter:new}:config");

        Long execute = redisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), asList);
        if (execute == 1) {
            logger.info("新布隆已经上线");
        } else {
            logger.info("老布隆在线，使用的依然是老布隆");
        }

        // 接着让这个任务过一段时间在延迟执行（延时任务+嵌套自己实现定时效果）nacos源码中
        ScheduleTaskThreadFactory.getInstance().execute(this, 7L, TimeUnit.DAYS);
    }

}
